package net.bithappens.hnqe.impl.rest.handler;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import net.bithappens.hnqe.InvalidDataException;
import net.bithappens.hnqe.InvalidInstanceException;
import net.bithappens.hnqe.graph.GraphNode;
import net.bithappens.hnqe.graph.GraphRelation;
import net.bithappens.hnqe.graph.GraphRelationMember;
import net.bithappens.hnqe.mapper.OperationInstructions;

import org.apache.log4j.Logger;

@Path("/hnqe/modify")
public class RestModify extends RootResource{

	private Logger log = Logger.getLogger(this.getClass());
	
	@Context 
	private UriInfo uriInfo;
	
	
	@PUT
	@Path("/pushNode/{instanceId}/{nodeUri}")
	@Consumes({"application/json"})
	public Response pushNodes(
			@PathParam("instanceId") String instanceId, 
			@PathParam("nodeUri") String nodeUri,
			@QueryParam("clearIfExist") @DefaultValue("false") String clearIfExist,
			@QueryParam("tryKeyMatch") @DefaultValue("false") String tryKeyMatch,
			GraphNode node) throws InvalidDataException, InvalidInstanceException{
		
		if(!nodeUri.equals(node.getUri().toString())){
			throw new InvalidDataException("Node uri and id uri doesn't match");
		}
		
		log.info("REST pushNode request for node "+nodeUri);
		
		Collection<GraphRelationMember> nodes = new ArrayList<GraphRelationMember>();
		nodes.add(node);
		
		boolean nodeExistsPrior = hnqe.getCachTraverseInterface().getNodeByUri(instanceId, node.getUri()) != null; 
		
		OperationInstructions instructions = new OperationInstructions(Boolean.valueOf(clearIfExist), Boolean.valueOf(tryKeyMatch));
		hnqe.getCachAccessInterface().pushNodes(instanceId, nodes, instructions);
		
		boolean nodeExistsPost = hnqe.getCachTraverseInterface().getNodeByUri(instanceId, node.getUri()) != null;
		
		if(!nodeExistsPrior && nodeExistsPost){
			//to distinguish if a node became updated or newly created
			//FIXME: change uri 
			return Response.created(uriInfo.getAbsolutePath()).build();
		} else {
			//in this case either the key match mechanism was used
			//or the node became overwritten
			return Response.ok().build();
		}
		
	}
	
	@PUT
	@Path("/pushRelation/{instanceId}/{relationUri}")
	@Consumes({"application/json"})
	public Response pushRelation(
			@PathParam("instanceId") String instanceId, 
			@PathParam("relationUri") String relationUri,
			@QueryParam("clearIfExist") @DefaultValue("false") String clearIfExist,
			@QueryParam("tryKeyMatch") @DefaultValue("false") String tryKeyMatch,
			GraphRelation relation) throws InvalidDataException, InvalidInstanceException{
		
		if(!relationUri.equals(relation.getUri().toString())){
			throw new InvalidDataException("Node uri and id uri doesn't match");
		}
		
		log.info("REST pushRelation request for relation "+relationUri);

		Collection<GraphRelation> relations = new ArrayList<GraphRelation>();
		relations.add(relation);
		
		boolean relationExistsPrior = hnqe.getCachTraverseInterface().getRelationByUri(instanceId, relation.getUri()) != null; 
		
		OperationInstructions instructions = new OperationInstructions(Boolean.valueOf(clearIfExist), Boolean.valueOf(tryKeyMatch));
		hnqe.getCachAccessInterface().pushRelations(instanceId, relations, instructions);
		
		boolean relationExistsPost = hnqe.getCachTraverseInterface().getRelationByUri(instanceId, relation.getUri()) != null;
		
		if(!relationExistsPrior && relationExistsPost){
			//FIXME: change uri 
			return Response.created(uriInfo.getAbsolutePath()).build();
		} else {
			//in this case either the key match mechanism was used
			//or the relation became overwritten
			return Response.ok().build();
		}
	}
	
	
	@DELETE
	@Path("/graphEntry/{instanceId}/{resourceUri}")
	public void deleteGraphEntries(
			@PathParam("instanceId") String instanceId, 
			@PathParam("resourceUri") String resourceUri) throws URISyntaxException, InvalidInstanceException{
		
		log.info("REST delete graphEntry request for resource "+resourceUri);
		
		Collection<URI> entries = new ArrayList<URI>();
		entries.add(new URI(resourceUri));
		
		hnqe.getCachAccessInterface().deleteGraphEntries(instanceId, entries);
				
	}

}
